Tweak how source paths are passed to the compiler
authorAlex Crichton <alex@alexcrichton.com>
Wed, 14 Jan 2015 03:10:16 +0000 (19:10 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 14 Jan 2015 03:45:05 +0000 (19:45 -0800)
All paths printed will now be absolute paths unless the path is a descendant of
the current directory. This should keep error messages and warnings of a
reasonable length when working with the local project while still allowing
errors in registry/git dependencies to be tracked down.

Special care is taken in these situations to ensure that the error message from
the compiler prints a reasonable path.

Closes #209
Closes #694

src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_bench.rs
tests/test_cargo_build_lib.rs
tests/test_cargo_compile.rs
tests/test_cargo_compile_custom_build.rs
tests/test_cargo_cross_compile.rs
tests/test_cargo_doc.rs
tests/test_cargo_profiles.rs
tests/test_cargo_run.rs

index 1b4843f90310ee59f922a37270eacbd40660b94a..41dca8dbd723bdc4575d8e0a516a4bc22795ae06 100644 (file)
@@ -1,5 +1,6 @@
-use std::collections::hash_map::HashMap;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
+use std::collections::hash_map::HashMap;
+use std::os;
 use std::str;
 use std::sync::Arc;
 
@@ -29,6 +30,7 @@ pub struct Context<'a, 'b: 'a> {
     pub compilation: Compilation,
     pub build_state: Arc<BuildState>,
     pub exec_engine: Arc<Box<ExecEngine>>,
+    pub cwd: Path,
 
     env: &'a str,
     host: Layout,
@@ -60,6 +62,9 @@ impl<'a, 'b: 'a> Context<'a, 'b> {
         };
         let target_triple = config.target().map(|s| s.to_string());
         let target_triple = target_triple.unwrap_or(config.rustc_host().to_string());
+        let cwd = try!(os::getcwd().chain_error(|| {
+            human("failed to get the current directory")
+        }));
         Ok(Context {
             target_triple: target_triple,
             env: env,
@@ -78,6 +83,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> {
             build_state: Arc::new(BuildState::new(build_config.clone(), deps)),
             build_config: build_config,
             exec_engine: Arc::new(Box::new(ProcessEngine) as Box<ExecEngine>),
+            cwd: cwd,
         })
     }
 
index d93b2540e4a13fd9d102b14a9ca5e66d1a9180dd..a707679658fc8df4311113c32f048005d7d65344 100644 (file)
@@ -63,7 +63,7 @@ pub fn prepare_target(cx: &mut Context, pkg: &Package, target: &Target,
     // indicates that the target is fresh.
     let dep_info = dep_info_loc(cx, pkg, target, kind);
     let mut are_files_fresh = use_pkg ||
-                              try!(calculate_target_fresh(pkg, &dep_info));
+                              try!(calculate_target_fresh(&dep_info));
 
     // Second bit of the freshness calculation, whether rustc itself, the
     // target are fresh, and the enabled set of features are all fresh.
@@ -226,8 +226,15 @@ fn mk_fingerprint<T: Hash<SipHasher>>(cx: &Context, data: &T) -> String {
     util::to_hex(hasher.finish())
 }
 
-fn calculate_target_fresh(pkg: &Package, dep_info: &Path) -> CargoResult<bool> {
-    let line = match BufferedReader::new(File::open(dep_info)).lines().next() {
+fn calculate_target_fresh(dep_info: &Path) -> CargoResult<bool> {
+    macro_rules! fs_try {
+        ($e:expr) => (match $e { Ok(e) => e, Err(..) => return Ok(false) })
+    }
+    let mut f = BufferedReader::new(fs_try!(File::open(dep_info)));
+    // see comments in append_current_dir for where this cwd is manifested from.
+    let cwd = fs_try!(f.read_until(0));
+    let cwd = Path::new(&cwd[..cwd.len()-1]);
+    let line = match f.lines().next() {
         Some(Ok(line)) => line,
         _ => return Ok(false),
     };
@@ -250,7 +257,7 @@ fn calculate_target_fresh(pkg: &Package, dep_info: &Path) -> CargoResult<bool> {
             file.push(' ');
             file.push_str(deps.next().unwrap())
         }
-        match fs::stat(&pkg.get_root().join(file.as_slice())) {
+        match fs::stat(&cwd.join(file.as_slice())) {
             Ok(stat) if stat.modified <= mtime => {}
             Ok(stat) => {
                 info!("stale: {} -- {} vs {}", file, stat.modified, mtime);
@@ -289,3 +296,18 @@ fn filename(target: &Target) -> String {
     };
     format!("{}{}-{}", flavor, kind, target.get_name())
 }
+
+// The dep-info files emitted by the compiler all have their listed paths
+// relative to whatever the current directory was at the time that the compiler
+// was invoked. As the current directory may change over time, we need to record
+// what that directory was at the beginning of the file so we can know about it
+// next time.
+pub fn append_current_dir(path: &Path, cwd: &Path) -> CargoResult<()> {
+    let mut f = try!(File::open_mode(path, io::Open, io::ReadWrite));
+    let contents = try!(f.read_to_end());
+    try!(f.seek(0, io::SeekSet));
+    try!(f.write(cwd.as_vec()));
+    try!(f.write(&[0]));
+    try!(f.write(&contents[]));
+    Ok(())
+}
index 15b16b1d4444100ba38c9cf9db6f9e0614c764a8..c18facd689380db2a5c96188d29a4248f491edc6 100644 (file)
@@ -489,6 +489,7 @@ fn rustc(package: &Package, target: &Target,
 
         let rustc_dep_info_loc = root.join(target.file_stem()).with_extension("d");
         let dep_info_loc = fingerprint::dep_info_loc(cx, package, target, kind);
+        let cwd = cx.cwd.clone();
 
         Ok((Work::new(move |desc_tx| {
             let mut rustc = rustc;
@@ -525,6 +526,7 @@ fn rustc(package: &Package, target: &Target,
             }));
 
             try!(fs::rename(&rustc_dep_info_loc, &dep_info_loc));
+            try!(fingerprint::append_current_dir(&dep_info_loc, &cwd));
 
             Ok(())
 
@@ -559,11 +561,10 @@ fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
 fn rustdoc(package: &Package, target: &Target,
            cx: &mut Context) -> CargoResult<Work> {
     let kind = Kind::Target;
-    let pkg_root = package.get_root();
     let cx_root = cx.layout(package, kind).proxy().dest().join("doc");
-    let rustdoc = try!(process(CommandType::Rustdoc, package, target, cx))
-                  .cwd(pkg_root.clone());
-    let mut rustdoc = rustdoc.arg(target.get_src_path())
+    let rustdoc = try!(process(CommandType::Rustdoc, package, target, cx));
+    let mut rustdoc = rustdoc.arg(root_path(cx, package, target))
+                         .cwd(cx.cwd.clone())
                          .arg("-o").arg(cx_root)
                          .arg("--crate-name").arg(target.get_name());
 
@@ -614,6 +615,20 @@ fn rustdoc(package: &Package, target: &Target,
     }))
 }
 
+// The path that we pass to rustc is actually fairly important because it will
+// show up in error messages and the like. For this reason we take a few moments
+// to ensure that something shows up pretty reasonably.
+//
+// The heuristic here is fairly simple, but the key idea is that the path is
+// always "relative" to the current directory in order to be found easily. The
+// path is only actually relative if the current directory is an ancestor if it.
+// This means that non-path dependencies (git/registry) will likely be shown as
+// absolute paths instead of relative paths.
+fn root_path(cx: &Context, pkg: &Package, target: &Target) -> Path {
+    let absolute = pkg.get_root().join(target.get_src_path());
+    absolute.path_relative_from(&cx.cwd).unwrap_or(absolute)
+}
+
 fn build_base_args(cx: &Context,
                    mut cmd: CommandPrototype,
                    pkg: &Package,
@@ -621,8 +636,11 @@ fn build_base_args(cx: &Context,
                    crate_types: &[&str]) -> CommandPrototype {
     let metadata = target.get_metadata();
 
+    // Move to cwd so the root_path() passed below is actually correct
+    cmd = cmd.cwd(cx.cwd.clone());
+
     // TODO: Handle errors in converting paths into args
-    cmd = cmd.arg(target.get_src_path());
+    cmd = cmd.arg(root_path(cx, pkg, target));
 
     cmd = cmd.arg("--crate-name").arg(target.get_name());
 
index 55692edb1e126cf5f3296d980ddeffd9e6665b0d..70c75fdd1982566695d6958af4eac10d030457b5 100644 (file)
@@ -840,8 +840,8 @@ test!(bench_with_examples {
                 execs().with_status(0)
                        .with_stdout(format!("\
 {compiling} testbench v6.6.6 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name testbench --crate-type lib [..]`
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name testbench --crate-type lib [..]`
+{running} `rustc src{sep}lib.rs --crate-name testbench --crate-type lib [..]`
+{running} `rustc src{sep}lib.rs --crate-name testbench --crate-type lib [..]`
 {running} `rustc benches{sep}testb1.rs --crate-name testb1 --crate-type bin \
         [..] --test [..]`
 {running} `{dir}{sep}target{sep}release{sep}testb1-[..] --bench`
index 6da91566935b7b826d55bc49bce9572373dde74f..6b6064a3a4d2b1b01de2bffa6c248f8ed381545c 100644 (file)
@@ -9,7 +9,7 @@ fn setup() {
 fn verbose_output_for_lib(p: &ProjectBuilder) -> String {
     format!("\
 {compiling} {name} v{version} ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name {name} --crate-type lib -g \
+{running} `rustc src{sep}lib.rs --crate-name {name} --crate-type lib -g \
         -C metadata=[..] \
         -C extra-filename=-[..] \
         --out-dir {dir}{sep}target \
index d03c40b6e74d2d807134a80e6bc23fabbac4f79b..df3be91b1d508bb527553bab15b387cbf46d3705 100644 (file)
@@ -751,7 +751,7 @@ test!(lto_build {
     assert_that(p.cargo_process("build").arg("-v").arg("--release"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}main.rs --crate-name test --crate-type bin \
+{running} `rustc src{sep}main.rs --crate-name test --crate-type bin \
         -C opt-level=3 \
         -C lto \
         --cfg ndebug \
@@ -780,7 +780,7 @@ test!(verbose_build {
     assert_that(p.cargo_process("build").arg("-v"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib -g \
+{running} `rustc src{sep}lib.rs --crate-name test --crate-type lib -g \
         -C metadata=[..] \
         -C extra-filename=-[..] \
         --out-dir {dir}{sep}target \
@@ -808,7 +808,7 @@ test!(verbose_release_build {
     assert_that(p.cargo_process("build").arg("-v").arg("--release"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
+{running} `rustc src{sep}lib.rs --crate-name test --crate-type lib \
         -C opt-level=3 \
         --cfg ndebug \
         -C metadata=[..] \
@@ -853,7 +853,7 @@ test!(verbose_release_build_deps {
     assert_that(p.cargo_process("build").arg("-v").arg("--release"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} foo v0.0.0 ({url})
-{running} `rustc {dir}{sep}foo{sep}src{sep}lib.rs --crate-name foo \
+{running} `rustc foo{sep}src{sep}lib.rs --crate-name foo \
         --crate-type dylib --crate-type rlib -C prefer-dynamic \
         -C opt-level=3 \
         --cfg ndebug \
@@ -864,7 +864,7 @@ test!(verbose_release_build_deps {
         -L dependency={dir}{sep}target{sep}release{sep}deps \
         -L dependency={dir}{sep}target{sep}release{sep}deps`
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
+{running} `rustc src{sep}lib.rs --crate-name test --crate-type lib \
         -C opt-level=3 \
         --cfg ndebug \
         -C metadata=[..] \
index 3cdd0daf50c1027fe7b77f8044cb90c5d49c6f7c..92543d4e07f62b898f87346c83f9eda5e20b2f3b 100644 (file)
@@ -364,9 +364,9 @@ test!(links_passes_env_vars {
                 execs().with_status(0)
                        .with_stdout(format!("\
 {compiling} [..] v0.5.0 (file://[..])
-{running} `rustc build.rs [..]`
+{running} `rustc [..]build.rs [..]`
 {compiling} [..] v0.5.0 (file://[..])
-{running} `rustc build.rs [..]`
+{running} `rustc [..]build.rs [..]`
 {running} `[..]`
 {running} `[..]`
 {running} `[..]`
@@ -563,7 +563,7 @@ test!(propagation_of_l_flags {
                 execs().with_status(0)
                        .with_stdout(format!("\
 {compiling} a v0.5.0 (file://[..])
-{running} `rustc build.rs [..]`
+{running} `rustc a[..]build.rs [..]`
 {compiling} b v0.5.0 (file://[..])
 {running} `rustc [..] --crate-name b [..]-L foo[..]`
 {running} `[..]a-[..]build-script-build[..]`
@@ -691,7 +691,7 @@ test!(build_cmd_with_a_build_cmd {
 {compiling} b v0.5.0 (file://[..])
 {running} `rustc [..] --crate-name b [..]`
 {compiling} a v0.5.0 (file://[..])
-{running} `rustc build.rs [..] --extern b=[..]`
+{running} `rustc a[..]build.rs [..] --extern b=[..]`
 {running} `[..]a-[..]build-script-build[..]`
 {running} `rustc [..]lib.rs --crate-name a --crate-type lib -g \
     -C metadata=[..] -C extra-filename=-[..] \
index 73fb1b39cbfc229bfd5c5594ab1871f177d564c7..668a81ab690889a1cd3938f38b36baf863884953 100644 (file)
@@ -495,7 +495,7 @@ test!(cross_with_a_build_script {
 {compiling} foo v0.0.0 (file://[..])
 {running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}foo-[..]`
 {running} `{dir}{sep}target{sep}build{sep}foo-[..]build-script-build`
-{running} `rustc {dir}{sep}src{sep}main.rs [..] --target {target} [..]`
+{running} `rustc src{sep}main.rs [..] --target {target} [..]`
 ", compiling = COMPILING, running = RUNNING, target = target,
    dir = p.root().display(), sep = path::SEP).as_slice()));
 });
@@ -562,21 +562,21 @@ test!(build_script_needed_for_host_and_target {
                 execs().with_status(0)
                        .with_stdout(format!("\
 {compiling} d1 v0.0.0 (file://{dir})
-{running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}d1-[..]`
+{running} `rustc d1{sep}build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}d1-[..]`
 {running} `{dir}{sep}target{sep}build{sep}d1-[..]build-script-build`
 {running} `{dir}{sep}target{sep}build{sep}d1-[..]build-script-build`
-{running} `rustc {dir}{sep}d1{sep}src{sep}lib.rs [..] --target {target} [..] \
+{running} `rustc d1{sep}src{sep}lib.rs [..] --target {target} [..] \
            -L /path/to/{target}`
-{running} `rustc {dir}{sep}d1{sep}src{sep}lib.rs [..] \
+{running} `rustc d1{sep}src{sep}lib.rs [..] \
            -L /path/to/{host}`
 {compiling} d2 v0.0.0 (file://{dir})
-{running} `rustc {dir}{sep}d2{sep}src{sep}lib.rs [..] \
+{running} `rustc d2{sep}src{sep}lib.rs [..] \
            -L /path/to/{host}`
 {compiling} foo v0.0.0 (file://{dir})
 {running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}foo-[..] \
            -L /path/to/{host}`
 {running} `{dir}{sep}target{sep}build{sep}foo-[..]build-script-build`
-{running} `rustc {dir}{sep}src{sep}main.rs [..] --target {target} [..] \
+{running} `rustc src{sep}main.rs [..] --target {target} [..] \
            -L /path/to/{target}`
 ", compiling = COMPILING, running = RUNNING, target = target, host = host,
    dir = p.root().display(), sep = path::SEP).as_slice()));
index 2e963802b6318dacabee0857adf7fa731b6557a1..e26f46ebfb98c854d3043296fac20de81d04f09d 100644 (file)
@@ -180,7 +180,7 @@ test!(doc_only_bin {
             pub fn bar() {}
         "#);
 
-    assert_that(p.cargo_process("doc"),
+    assert_that(p.cargo_process("doc").arg("-v"),
                 execs().with_status(0));
 
     assert_that(&p.root().join("target/doc"), existing_dir());
index c4ee0edb37de34708956ef1bc7efdb0a64f6cc9d..e4f0cd67c2909f5431a4520b439529d9bbd3d0fe 100644 (file)
@@ -27,7 +27,7 @@ test!(profile_overrides {
     assert_that(p.cargo_process("build").arg("-v"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
+{running} `rustc src{sep}lib.rs --crate-name test --crate-type lib \
         -C opt-level=1 \
         --cfg ndebug \
         -C metadata=[..] \
@@ -81,7 +81,7 @@ test!(top_level_overrides_deps {
     assert_that(p.cargo_process("build").arg("-v").arg("--release"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} foo v0.0.0 ({url})
-{running} `rustc {dir}{sep}foo{sep}src{sep}lib.rs --crate-name foo \
+{running} `rustc foo{sep}src{sep}lib.rs --crate-name foo \
         --crate-type dylib --crate-type rlib -C prefer-dynamic \
         -C opt-level=1 \
         -g \
@@ -92,7 +92,7 @@ test!(top_level_overrides_deps {
         -L dependency={dir}{sep}target{sep}release{sep}deps \
         -L dependency={dir}{sep}target{sep}release{sep}deps`
 {compiling} test v0.0.0 ({url})
-{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
+{running} `rustc src{sep}lib.rs --crate-name test --crate-type lib \
         -C opt-level=1 \
         -g \
         -C metadata=[..] \
index bc727a9e68e49e06d6933f011ee34eafd01574b5..f8077f395644d11d37660716e41c610ae6fe4449 100644 (file)
@@ -266,7 +266,7 @@ test!(example_with_release_flag {
     assert_that(p.cargo_process("run").arg("-v").arg("--release").arg("--example").arg("a"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} bar v0.0.1 ({url})
-{running} `rustc src{sep}bar.rs --crate-name bar --crate-type lib \
+{running} `rustc bar{sep}src{sep}bar.rs --crate-name bar --crate-type lib \
         -C opt-level=3 \
         --cfg ndebug \
         -C metadata=[..] \
@@ -276,7 +276,7 @@ test!(example_with_release_flag {
         -L dependency={dir}{sep}target{sep}release{sep}deps \
         -L dependency={dir}{sep}target{sep}release{sep}deps`
 {compiling} foo v0.0.1 ({url})
-{running} `rustc {dir}{sep}examples{sep}a.rs --crate-name a --crate-type bin \
+{running} `rustc examples{sep}a.rs --crate-name a --crate-type bin \
         -C opt-level=3 \
         --cfg ndebug \
         --out-dir {dir}{sep}target{sep}release{sep}examples \
@@ -297,7 +297,7 @@ fast2
     assert_that(p.process(cargo_dir().join("cargo")).arg("run").arg("-v").arg("--example").arg("a"),
                 execs().with_status(0).with_stdout(format!("\
 {compiling} bar v0.0.1 ({url})
-{running} `rustc src{sep}bar.rs --crate-name bar --crate-type lib \
+{running} `rustc bar{sep}src{sep}bar.rs --crate-name bar --crate-type lib \
         -g \
         -C metadata=[..] \
         -C extra-filename=[..] \
@@ -306,7 +306,7 @@ fast2
         -L dependency={dir}{sep}target{sep}deps \
         -L dependency={dir}{sep}target{sep}deps`
 {compiling} foo v0.0.1 ({url})
-{running} `rustc {dir}{sep}examples{sep}a.rs --crate-name a --crate-type bin \
+{running} `rustc examples{sep}a.rs --crate-name a --crate-type bin \
         -g \
         --out-dir {dir}{sep}target{sep}examples \
         --emit=dep-info,link \